﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Data.SQLite;
using System.IO.Ports;
using System.Globalization;
using System.Windows.Forms.DataVisualization.Charting;
using System.IO;
using System.Data.SqlClient;
using System.Windows.Forms.VisualStyles;

namespace WSD
{

    public partial class Form1 : Form
    {
        SQLiteConnection conn;
        public Form1()
        {
            InitializeComponent();
            this.Load += new EventHandler(Form1_Load);

        }
        static string curpath = Environment.CurrentDirectory;
        static string filepath = @curpath.Replace("bin\\Debug", "database\\") + "Database.db";
        private void Form1_Load(object sender, EventArgs e)
        {

            CreateDatabase();//创建数据库
            cBox_comport.DataSource = SerialPort.GetPortNames();//列举com放在下拉框
            chart1.Series[0].Points.Clear();

            conn = new SQLiteConnection();
            conn.ConnectionString = "data source=" + filepath;
            conn.Open();//连接数据库
            InitializeDatebase();//初始化数据库
            serialPort1.Close();
            timer1.Start();
        }
        private void CreateDatabase()//创建数据库
        {
            if (!File.Exists(filepath))
            {
                Directory.CreateDirectory(filepath.Replace("\\Database.db", ""));//若目录不存在自动创建目录
                SQLiteConnection.CreateFile(filepath);//创建数据库
            }
            else
            {
                Console.WriteLine("数据库已存在");
            }
        }
        private void InitializeDatebase()//初始化数据库(清空)
        {
            try
            {
                SQLiteCommand cmdin = new SQLiteCommand(conn);
                cmdin.CommandText = @"CREATE TABLE ""wsd"" (
	                                    ""id""	INTEGER UNIQUE,
	                                    ""tem""	INTEGER,
	                                    ""hum""	INTEGER,
	                                    PRIMARY KEY(""id"" AUTOINCREMENT)
                                        );";
                cmdin.ExecuteNonQuery();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            SQLiteCommand cmddel = new SQLiteCommand(conn);
            cmddel.CommandText = "DELETE FROM wsd;";//清空wsd表
            cmddel.ExecuteNonQuery();
            SQLiteCommand reset = new SQLiteCommand(conn);
            reset.CommandText = "UPDATE sqlite_sequence set seq=0 WHERE name='wsd'";//重置wsd表中id
            reset.ExecuteNonQuery();
        }
        private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            
            try
            {
                int dateLen = serialPort1.BytesToRead;//检查串口中有多少字节数据可读取
                byte[] buffer = new byte[dateLen];
                serialPort1.Read(buffer, 0, dateLen);//从串口读入数据到buffer
                Console.WriteLine(AddToDatabase(UnCodeHex(ByteToHex(buffer))));//数据转换到16进制字符串，然后解码，然后添加到数据库
                                                                               //AddDataSetToChart(GetLasted30Data(), chart1);}
            }
            catch
            {
                //Console.WriteLine("wwwwwwwwwwwwwwwwwwwww");
            }
        }
        private string ByteToHex(byte[] buffer)
        {
            StringBuilder sb = new StringBuilder();
            foreach (byte item in buffer)
            {
                sb.AppendFormat(item.ToString("X2"));
            }
            return sb.ToString();
        }
        private float[] UnCodeHex(string info) // 将字符串解码为数组info
        {
            info = info.Replace(" ", "");
            // 数组info第0位为温度，第1位为湿度
            float[] output = new float[2];

            // 获取数据位的长度
            try
            {
                int dataLength = int.Parse(info.Substring(4, 2), System.Globalization.NumberStyles.HexNumber);
                string temperatureHex = info.Substring(6, dataLength);
                string humidityHex = info.Substring(6 + dataLength, dataLength);
                byte[] temperatureBytes = Enumerable.Range(0, temperatureHex.Length)
                                                .Where(x => x % 2 == 0)
                                                .Select(x => Convert.ToByte(temperatureHex.Substring(x, 2), 16))
                                                .ToArray();
                byte[] humidityBytes = Enumerable.Range(0, humidityHex.Length)
                                                 .Where(x => x % 2 == 0)
                                                 .Select(x => Convert.ToByte(humidityHex.Substring(x, 2), 16))
                                                 .ToArray();
                if (BitConverter.IsLittleEndian)
                {
                    Array.Reverse(humidityBytes);
                    Array.Reverse(temperatureBytes);
                }
                output[0] = BitConverter.ToSingle(temperatureBytes, 0);
                output[1] = BitConverter.ToSingle(humidityBytes, 0);
            }
            catch { }

            // 根据数据位长度截取温度和湿度的十六进制数据
            // 将十六进制字符串转换为字节数
            // 将字节数组转换为浮点数


            return output;
        }


        private string AddToDatabase(float[] temhum)//传入数据添加到数据库,传回字符串提示
        {
            SQLiteCommand cmd = new SQLiteCommand(conn);
            cmd.CommandText = "insert into wsd (tem, hum) values(:tem,:hum) ";
            cmd.Parameters.Add(new SQLiteParameter(":tem", temhum[0]));
            cmd.Parameters.Add(new SQLiteParameter(":hum", temhum[1]));
            
            return "添加了"+ cmd.ExecuteNonQuery() + "条数据" + "(" + temhum[0] + "," + temhum[1] + ")";
        }



        private void btn_Close_Click(object sender, EventArgs e)
        {
            if (serialPort1.IsOpen)
            {
                serialPort1.Close();//关闭端口
            }
            tmUpdate.Enabled = false;//禁用绘图定时器
            
        }

        private void cBox_comport_SelectedValueChanged(object sender, EventArgs e)//当在下拉框选中端口名时赋值给serialPort1
        {
            try { serialPort1.PortName = cBox_comport.SelectedItem.ToString(); }
            catch { }
            serialPort1.BaudRate = 9600;//暂时设为9600
        }

        private void cBox_BaudRate_SelectedValueChanged(object sender, EventArgs e)
        {
            try
            {
                serialPort1.BaudRate = int.Parse(cBox_BaudRate.SelectedItem.ToString());

            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }


        private void cBox_DateBit_SelectedValueChanged(object sender, EventArgs e)
        {
            if (int.Parse(cBox_DateBit.SelectedItem.ToString()) == 8)
            {
                try
                {
                    serialPort1.DataBits = int.Parse(cBox_DateBit.SelectedItem.ToString());

                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }
            else
            {
                MessageBox.Show("暂不支持");
            }

        }

        private void cBox_StopBit_SelectedValueChanged(object sender, EventArgs e)
        {
            try
            {
                serialPort1.StopBits = StopBits.One;

            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

        private void cBox_ExamBot_SelectedValueChanged(object sender, EventArgs e)
        {
            try
            {
                serialPort1.Parity = Parity.None;

            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            if (serialPort1.IsOpen)
            {

                try
                {
                    byte[] buffer = { 0x01, 0x03, 0x00, 0x00, 0x00, 0x04, 0x44, 0x09 };//一次读取温湿度单精度32浮点
                    serialPort1.Write(buffer, 0, buffer.Length);
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);

                }
            }
            //Console.WriteLine(1111111111111111111);

        }

        private void btn_Open_Click(object sender, EventArgs e)
        {
            try
            {
                serialPort1.Open();
            }
            catch { }
            
            
            chart1.Series[0].Points.Clear();//清除已有数据点
            chart1.Series[1].Points.Clear();
            chart1.Invalidate();
            tmUpdate.Start();

        }
        private void AddDataPointsToChart(int PointsCount, Chart chart)
        {
            if (chart.Series[0].Points.Count == PointsCount)
            {
                
                for (int i = 0; i < chart.Series[0].Points.Count - 1; i++)
                {
                    chart.Series[0].Points[i].SetValueXY(i + 1, chart.Series[0].Points[i + 1].GetValueByName("Y"));
                    chart.Series[1].Points[i].SetValueXY(i + 1, chart.Series[1].Points[i + 1].GetValueByName("Y"));
                }
                chart.Series[0].Points[chart.Series[0].Points.Count - 1].SetValueXY(chart.Series[0].Points.Count, GetLastestData()[0]);
                chart.Series[1].Points[chart.Series[1].Points.Count - 1].SetValueXY(chart.Series[1].Points.Count, GetLastestData()[1]);
                chart.Invalidate();
            }
            else
            {
                chart.Series[0].Points.AddXY(chart.Series[0].Points.Count + 1, GetLastestData()[0]);
                chart.Series[1].Points.AddXY(chart.Series[1].Points.Count + 1, GetLastestData()[1]);
            }

        }



        
        //从数据库获取最新的温湿度并以数组形式返回
        private float[] GetLastestData()
        {
            float[] LastestData = new float[2];
            SQLiteCommand cmd = new SQLiteCommand(conn);
            cmd.CommandText = "SELECT tem,hum FROM wsd ORDER by id DESC LIMIT 1";
            //查询数据库中id最大的,返回temhum
            SQLiteDataReader sReader = cmd.ExecuteReader();
            try
            {
                while (sReader.Read())
                {
                    float tem = sReader.GetFloat(0);
                    float hum = sReader.GetFloat(1);
                    LastestData[0] = tem;
                    LastestData[1] = hum;
                }
            }catch (Exception ex) { }
            sReader.Close();
            return LastestData;
        }

        private void tmUpdate_Tick(object sender, EventArgs e)
        {

            AddDataPointsToChart(30, chart1);
            
        }
    }

}
